#include "bmp.h"
#include "lcd.h"

void display(const char *bmpname, const struct LCD_info *plcd, uint8_t mode)
{
    FILE *fp = fopen(bmpname, "r");
    struct bitmap_header head;
    struct bitmap_info   info;
    fread(&head, sizeof(head), 1, fp);
    fread(&info, sizeof(info), 1, fp);
    if(info.compression)
    {
        struct rgb_quad quad;
        fread(&quad, sizeof(quad), 1, fp);
    }
    int bmp_bpp = info.bit_count; // 24比特位，图片中的一个像素点=3个字节
    printf("%d × %d [%d]\n", info.width, info.height, head.size);

    // 3. 将BMP中的RGB数据读出来
    // 申请一块能刚好放下RGB数据的内存
    long a = ftell(fp);
    fseek(fp, 0L, SEEK_END);
    long b = ftell(fp);
    char *rgb_data = malloc(b-a);

    fseek(fp, a, SEEK_SET);
    fread(rgb_data, b-a, 1, fp);
    fclose(fp);

    // 解析一下用户的显示图片的模式
    bool zoom;
    zoom =  (info.width>plcd->width || info.height>plcd->height);
    zoom = zoom && (mode & ZOOM); // 在图片大于LCD尺寸条件下用户要求缩小才缩小

    // 计算BMP一行的真实大小
    int pad = ( 4-(info.width*3)%4 ) % 4; // 每一行末尾填充的无效字节，用来保证一行字节数是4的倍数
    int bmp_line_size = info.width * 3 + pad;

    // 4. 妥当地显示图片（将rgb_data指向的RGB数据，搬到fb_mem指向的映射内存中）
    int bmp_w = zoom ? info.width/2 : info.width;
    int bmp_h = zoom ? info.height/2: info.height;
    int x = (plcd->width-bmp_w)/2;
    int y = (plcd->height-bmp_h)/2;

    bool center;
    center = (bmp_w<plcd->width || bmp_h<plcd->height);
    center = center && (mode & CENTER);// 在图片小于LCD尺寸条件下用户要求居中才居中

    int lcd_w = center ? plcd->width - x : plcd->width;
    int lcd_h = center ? plcd->height- y : plcd->height;

    char *fbm = plcd->fb_mem +  (center ? (y*800+x)*4 : 0);
    for(int j=0, m=0; m<info.height && j<lcd_h; j++, zoom?(m+=2):m++)
    {
        // 每一行的偏移量
        int lcd_offset = 800*4*j;

        // 让rgb从RGB数据的最后一行开始
        int rgb_offset = bmp_line_size * (info.height-m-1);

        // 将图片的一行显示出来
        for (int i=0, k=0; k<info.width && i<lcd_w ; i++, zoom?(k+=2):k++)
        {
            memcpy(fbm + 4*i + lcd_offset,
                   rgb_data + k*3+ rgb_offset,3); // 显示下一个像素点
        }
    }

    free(rgb_data);
}